package com.nineclock.auth.aop;

import com.nineclock.auth.dto.NcOauthTokenDTO;
import com.nineclock.auth.entity.IntegrationAuthenticationEntity;
import com.nineclock.auth.threadlocal.IntegrationAuthenticationHolder;
import com.nineclock.auth.threadlocal.UserHolder;
import com.nineclock.common.entity.Result;
import com.nineclock.common.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Aspect
@Component
@Slf4j
public class AuthTokenAspect {
    private static final String AUTH_TYPE_PARAM_NAME = "auth_type";

    @Autowired
    HttpServletRequest request;

    //环绕增强，  对生成token的方法进行增强
    @Around("execution( * org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{

        Result result = null;
        Object resultObj = null;
        try {
            //前置增强
            //把request请求对象中的请求参数封装到 IntegrationAuthenticationEntity 实体类对象
            IntegrationAuthenticationEntity entity = new IntegrationAuthenticationEntity();
            //获取request对象，从request中获取数据
//            //从 域中获取 request对象
//            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            //获取 认证类型，并存入到entity
            String authType = request.getParameter(AUTH_TYPE_PARAM_NAME);
            entity.setAuthType(authType);
            //获取其他参数， 存入 entity中
            Map<String, String[]> parameterMap = request.getParameterMap();
            entity.setAuthParameters(parameterMap);


            //把封装好的IntegrationAuthenticationEntity 存入 当前线程中
            IntegrationAuthenticationHolder.set(entity);

            log.info("认证实体对象信息：" + JsonUtils.toString(entity));
            //执行原始方法
            resultObj = joinPoint.proceed();
            //对返回值进行增强(转换为 ResponseEntity类型)
            ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>) resultObj;

            if( responseEntity.getStatusCode().is2xxSuccessful()){
                //获取 认证后的token
                OAuth2AccessToken accessToken = responseEntity.getBody();

                NcOauthTokenDTO oauthTokenDTO = new NcOauthTokenDTO();
                oauthTokenDTO.setOauth2AccessToken(accessToken);
                oauthTokenDTO.setUser(UserHolder.get());

                result = Result.success(oauthTokenDTO);
            }else{
                result = Result.errorCodeMessage(responseEntity.getStatusCodeValue(), "获取令牌失败");
            }


        } finally {
            //移除信息
            IntegrationAuthenticationHolder.remove();
        }


        return ResponseEntity.ok().body(result);
    }

}
